Spring cloud 应用程序分层与响应式
MVC(Model-View-Controller)

MVC(Model View Controller)是在软件工程中较为常见的一种架构模式,无论是 Spring cloud 以及 Spring、Spring boot 基本上我们都介绍过此模型。
如果要简单的理解 MVC 的话,我们可以从上图了解到,首先 Model 是拥有对数据直接访问的权利(例如数据库访问)。
而 Conttroller 则是可以控制应用程序的流程,并对事件作出响应,这也包括了对 Model 的操作。
最后则是 View ,他能够显示资料,通常为前端应用。在上图中 Controller 操纵 Model 进行数据的更新或插入,之后交给 View 进行显示给用户。

如果说前面我们介绍的都是 MVC 概述,那么通过上图我们可以详细的进行理解。首先浏览器一看是看到的并不是 View,而是 通过 DispathcherServlet 来调用视图渲染后返回给浏览器中。这里我们需要注意的是 DispathcheServlet 继承于 HttpServlet ,主要负责协调和组织不同组件来完成请求并返回响应的工作,他的流程如下:
- 浏览器发送请求,服务器接受请求并转交给 DispatcherServlet 进行处理
- DispatcherServlet 匹配在控制器中配置的映射路径,进行下一步处理
- View 请求将 Model 和 View 解析成 View,之后调用 render() 方法根据 Model 和 View 中的数据渲染出页面。
三层架构
这与 MVC 的三层架构有很大的关系,所谓三层架构即 表现层(UI)、业务逻辑层(Service)、数据访问层(Dao\Repository)三种,他们分别表示:
Responsitory 是存取和管理对象,而 Dao 则是存取对象
- 表现层:用于展示界面,接收用户请求并返回数据,为客户端提供应用程序的访问接口(View)
- 业务逻辑层:也称之为服务层,负责业务逻辑的处理,主要调用D哦曾对数据进行 CURD 的操作
- 数据访问层:与数据库进行交互的持久层,被 Service 调用,在 Spring Data JPA 中则由 Hibernate 进行实现。
WebFlux
反应式是关于异步和事件驱动的非堵塞应用程序,并且需要少量线程进行垂直扩展,而不是水平扩展(集群)。反应式系统具有某些特征,可以使其成为低延迟、高吞度量工作的理想选择。
WebFlux 是在 Spring Framework 5.0(5.0.0.M5)所引入的一种反应式 Web 框架。WebFlux 可以在资源有限的情况下提高系统的吞度量和垂直扩展,这意味着在同样情况下 WebFlux 的吞吐量明显优于 MVC。
响应式(反应式)与命令式
为了应对高并发环境下服务端开发,微软提出了一个实现异步编程方案,即 反应式编程(Reactive Programming)。其他技术和社区为了跟上脚步,因此向 Netifix 等公司都也提供了类似的技术,这使得 Java 平台也有了能够实现反应式编程的框架
响应式编程或反应式编程(Reactive programming)是一个面向数据流和 变化传播 的声明式编程范式(Declarative programming)。
响应式编程与命令式编程对立,他的目标是让计算机明白,而非流程,声明式编程不需要告诉电脑问题,即告诉结果,让机器自行解决
而响应式编程则是是意味着式子
a=b+c,这意味着 a 是由 b 和 c 计算而出,如果后续有变化会影响到 a 的值,这也是 即告诉结果,让机器自行解决命令式编程或指令式编程(Inperative programming),详细命令机器去处理一种事情而达到你想要的结果。
变化传递我们可以理解为在命令式变成中,假设式子为a=b+c那么 a 的值就来自 b和c计算出的,如果后续有变化不会影响到a的值,这也是为什么他是 细命令机器去处理一种事情而达到你想要的结果
Spring WebFlux 是一个从头开始构建的非堵塞Web框架,可利用多核下一代处理器并处理大量并发。而 WebFlux 与 Spring MVC 数据流的选择也各不相同,前者是 Reactive Streames,后者则是 Servlet API。

自然而然,既然 WebFlux 是用的是响应式数据流,而Spring MVC 选择的是 命令式数据流,自然而然 WebFlux 会更快。我认为上图很好的诠释了这一点,Spring MVC 是一个 响应 -> 准备数据 -> 返回数据 的一个过程。而 WebFlux 则是 响应 -> 返回数据 -> 开启一个新的 Work 线程进行准备 -> Work 线程完成工作 -> 返回结果 从而让对方觉得 WebFlux 会更快的一点。
Reactor
Peactor 框架由 Pivotal 基于 反应式编程(Reactive Programming) 思想进行实现,符合反应式编程的规范。
响应式编程
响应式编程(Reactive Programming)是一种非堵塞且事件驱动数据的开发方案,使用函数式编程的概念来操作数据流。
函数式编程是一种编程方式,将计算机的运算视为函数计算,如何直接和生动形象的表现出函数式编程的特点呢,那么下面的表达式就非常的清晰
过程式编程: var a = 1 + 2;
函数式编程: var result = subtract(multiply(add(1,2), 3), 4);其实函数式变成并没有什么特殊,他其实就是将一数复制给变量或者一个数组中,就这个意思。
函数变成最主要的是λ演算 (Iambda calculus),而λ演算可以 接受函数党组输出(参数)和输出(返回值),相比过程化编程相比,函数式编程里的函数可以随时调用
| 事件 | 方法 |
|---|---|
| 包含元素信息 | onNext() |
| 序列结束消息 | onComplete() |
| 序列出错消息 | onError() |
这是通知与订阅者对应的方法,但如果我们继续眼神可以了解到背压机制(与本文有关):
| 事件 | Iterable 迭代模式 (拉\pull) | Observable 观察模式(推\push) |
|---|---|---|
| 获取数据 | T next() | onNext() |
| 处理完成 | hasNext() | onCompleted() |
| 发现异常 | throws Exception | onError() |
1.事件发布者(Publisher) 主动推送数据给 订阅者(Subscriber),出发 onNext() 方法;
2.事件发布者发生异常,则触发 订阅者 的 onError() 方法进行异常捕获处理
3.事件发布者每次推送都触发一次 onNext() 方法,当所有推送无异常时, onCompleted() 方法在在最后触发一次。我们可以从被订阅者和订阅者理解为服务提供者和服务消费者。
如果 被订阅者发布的消息太快了,超过了订阅者的处理速度,那么这个时候就需要通过 背压机制(Backpressure),使得订阅者能够控制消费消息的速度。
实际上除了 迭代模式 (lterable) 其他的都是我们 响应式编程API的使用方式,实际上激素和观察者模式(Observable)的扩展。
Reactive Streams
他由 Netifix,TypeSafe、Pivatol共同制定,这是 Java 平台上 RxJava、Scala、Akka、Spring、Reactor 等项目的主要维护者所共同发起的。
反应式流(Reactive Streams)是一项倡议,主要用于反应式编程相关的规范以及接口提供标准。
他主要有四个组件构成,分别为发布者、订阅者、订阅、处理器等。除此还有三个接口最为主要:
- Publisher(事件发布者)
- Subscriber(订阅者)
- Subcription(订阅)
Mono 与 Flux
Mono 与 Flux 都是事件的发布者,也是 Reactor 的核心类:
- Mono
- 实现了 org.reactivestreams.Publisher 接口,用于返回单个数据
- Flux
- 同样实现了 org.reactivestreams.Publisher 接口,用于返回多个数据。
如果根据 ID 查询某个 User 对象,那么返回的肯定是单个数据,那么就需要使用 Mono<User>
但是如果要获取所有 User,则返回的是多个数据,需要使用 Flux<User>。
需要注意的是 Mono 与 Flux 之间可以 互相转换,对一个 Flux 序列进行技术操作,得到的结果是一个 Mono<Long> 对象,将多个 Mono 序列合并在一起,则得到的是 Flux 对象。
